package com.shop.loan.service.impl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.shop.loan.mapper.*;
import com.shop.loan.model.LoanOrder;
import com.shop.loan.model.common.Code;
import com.shop.loan.model.common.ResResult;
import com.shop.loan.model.entity.*;
import com.shop.loan.model.enums.*;
import com.shop.loan.model.vo.*;
import com.shop.loan.redis.RedisCache;
import com.shop.loan.redis.RedisLockUtil;
import com.shop.loan.redis.RedisUtil;
import com.shop.loan.rentaldata.RentalDataUtil;
import com.shop.loan.service.*;
import com.shop.loan.util.LoanOrderUtil;
import com.shop.loan.util.SysMsgUtil;
import com.shop.loan.util.Util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

@Slf4j
@Service
public class LoanOrderServiceImpl implements LoanOrderService {

    @Resource
    LoanOrderByMybatisMapper loanOrderByMybatisMapper;

    @Resource
    LoanOrderBillByMybatisMapper loanOrderBillByMybatisMapper;

    @Resource
    LoanOrderAuthByMybatisMapper loanOrderAuthByMybatisMapper;

    @Resource
    LoanOrderPayLogByMybatisMapper loanOrderPayLogByMybatisMapper;

    @Resource
    LoanOrderSignLogByMybatisMapper loanOrderSignLogByMybatisMapper;

    @Resource
    UserByMybatisMapper userByMybatisMapper;

    @Resource
    BlacklistByMybatisMapper blacklistByMybatisMapper;

    @Resource
    RedisUtil redisUtil;

    @Resource
    SysMsgUtil sysMsgUtil;

    @Resource
    RedisLockUtil redisLockUtil;

    @Resource
    SettingService settingService;

    @Resource
    AsyncService asyncService;

    @Resource
    MsgService msgService;

    @Lazy
    @Resource
    UserService userService;

    @Resource
    MachineRuleService machineRuleService;

    @Resource
    EruptUserDataService eruptUserDataService;

    @Resource
    StatisticsDayByMybatisMapper statisticsDayByMybatisMapper;

    @Resource
    LoanOrderLogisticsByMybatisMapper loanOrderLogisticsByMybatisMapper;

    @Resource
    RentalDataUtil rentalDataUtil;

    @Lazy
    @Resource
    LoanOrderUtil loanOrderUtil;

    @Resource
    LoanOrderDeviceInfoByMybatisMapper loanOrderDeviceInfoByMybatisMapper;

    @Resource
    ProductByMybatisMapper productByMybatisMapper;

    @Resource
    UserBankByMybatisMapper userBankByMybatisMapper;

    @Resource
    UserContactByMybatisMapper userContactByMybatisMapper;

    @Resource
    GoodsSizeByMybatisMapper goodsSizeByMybatisMapper;

    @Resource
    ContractByMybatisMapper contractByMybatisMapper;

    @Resource
    GoodsByMybatisMapper goodsByMybatisMapper;

    @Override
    public CheckOrderRes checkOrder(LoanOrderVo orderVo) {
        GoodsSizeByMybatis goodsSizeByMybatis = goodsSizeByMybatisMapper.selectByPrimaryKey(orderVo.getGoodsSizeId());
        GoodsByMybatis goodsByMybatis = goodsByMybatisMapper.selectByPrimaryKey(goodsSizeByMybatis.getGoodsId());
        ProductByMybatis productByMybatis = productByMybatisMapper.selectByPrimaryKey(goodsSizeByMybatis.getProductId());

        ContractByMybatis contractByMybatis = new ContractByMybatis();
        contractByMybatis.setAppShow(true);
        contractByMybatis.setStatus(true);
        List<ContractByMybatis> contractByMybatisList = contractByMybatisMapper.selectByList(contractByMybatis);

        CheckOrderRes checkOrderRes = new CheckOrderRes();
        checkOrderRes.setTotalPrice(goodsSizeByMybatis.getPrice());
        checkOrderRes.setUnitPrice(goodsSizeByMybatis.getPrice());
        checkOrderRes.setPledgeMoney(BigDecimal.ZERO);

        checkOrderRes.setContracts(contractByMybatisList);
        checkOrderRes.setLogistics(goodsByMybatis.getLogistics());

        if (productByMybatis != null) {
            Integer loanPeriodDay = productByMybatis.getLoanDay() / productByMybatis.getLoanPeriod();
            LoanOrderByMybatis loanOrderByMybatis = new LoanOrderByMybatis();
            loanOrderByMybatis.setMoney(productByMybatis.getMoney());
            loanOrderByMybatis.setPeriod(productByMybatis.getLoanPeriod());
            loanOrderByMybatis.setPeriodDay(loanPeriodDay);
            loanOrderByMybatis.setYearRate(productByMybatis.getYearRate());
            int betweenDay = loanOrderByMybatis.getPeriod() * loanOrderByMybatis.getPeriodDay();
            BigDecimal rateMoney = Util.getRateMoney(loanOrderByMybatis.getMoney(), loanOrderByMybatis.getYearRate(), betweenDay);
            loanOrderByMybatis.setRateMoney(rateMoney);

            List<LoanOrderBillByMybatis> periodDateList = Util.getPeriodList(loanOrderByMybatis);

            checkOrderRes.setBills(periodDateList);
            checkOrderRes.setLoanMoney(productByMybatis.getMoney());
            checkOrderRes.setLoanPeriod(productByMybatis.getLoanPeriod());
            checkOrderRes.setLoanRate(productByMybatis.getYearRate());
            checkOrderRes.setLoanDay(productByMybatis.getLoanDay());
        }
        checkOrderRes.setLogistics(goodsByMybatis.getLogistics());
        return checkOrderRes;
    }


    @Override
    public ResResult create(LoanOrderVo loanOrderVo, Boolean isar) {
        isar = isar != null && isar;
        if (!isar && loanOrderVo.getBankId() == null) {
            return new ResResult(Code.PARAM_LACK);
        }

        Jedis jedis = redisUtil.getJedis();
        String lockKey = RedisCache.createLoanOrderLock + loanOrderVo.getOpId();
        String lockValue = UUID.randomUUID().toString();
        try {
            if (!redisLockUtil.lock(jedis, lockKey, lockValue)) {
                return new ResResult(Code.RATE_HIGH);
            }
            UserByMybatis user = userByMybatisMapper.selectByPrimaryKey(loanOrderVo.getOpId());
            if (user.getUserStatus() != UserStatus.normal.getType().intValue()) {
                return new ResResult(Code.USER_STATUS_ERROR);
            }

            if (!user.getContactAuthStatus() || !user.getIdentityAuthStatus()) {
                return new ResResult(Code.USER_AUTH_LACK);
            }

            if (!isar && !user.getBankAuthStatus()) {
                return new ResResult(Code.USER_AUTH_LACK);
            }

            if (!user.getMachineStatus()) {
                return new ResResult(Code.USER_BLACK);
            }

            //校验用户是否在黑名单中
            Integer blackNum = blacklistByMybatisMapper.selectByMobileOrIdCard(user.getMobile(), user.getCardNum());
            if (blackNum != null && blackNum > 0) {
                return new ResResult(Code.USER_BLACK);
            }
            LoanOrderByMybatis numLoan = new LoanOrderByMybatis();
            numLoan.setUserId(loanOrderVo.getOpId());
            Integer totalNum = loanOrderByMybatisMapper.selectNum(numLoan);
            totalNum = totalNum == null ? 0 : totalNum;
            //身份证进行中订单数量
            Integer ingNum = user.getIngNum();
            ingNum = ingNum == null ? 1 : ingNum;
            Integer orderByIng = loanOrderByMybatisMapper.selectIngByIden(user.getCardNum());
            orderByIng = orderByIng == null ? 0 : orderByIng;
            if (orderByIng >= ingNum) {
                return new ResResult(Code.ORDER_ING);
            }

            GoodsSizeByMybatis goodsSizeByMybatis = goodsSizeByMybatisMapper.selectByPrimaryKey(loanOrderVo.getGoodsSizeId());
            if (goodsSizeByMybatis == null || goodsSizeByMybatis.getProductId() == null) {
                return new ResResult(Code.PARAM_INVALID);
            }

            ProductByMybatis product = productByMybatisMapper.selectByPrimaryKey(goodsSizeByMybatis.getProductId());
            if (product == null) {
                return new ResResult(Code.PARAM_INVALID);
            }
            user.setOrderEndNum(user.getOrderEndNum() == null ? 0 : user.getOrderEndNum());

            if (!isar) {
                UserBankByMybatis userBankByMybatis = userBankByMybatisMapper.selectByPrimaryKey(loanOrderVo.getBankId());
                if (userBankByMybatis == null || userBankByMybatis.getUserId() != loanOrderVo.getOpId().intValue()) {
                    return new ResResult(Code.PARAM_INVALID);
                }
            }

            Long serviceId = user.getServiceUserId();
            if (user.getServiceUserId() == null) {
                serviceId = eruptUserDataService.allotServiceByBefore(ServiceType.before_service, user.getId());
            }
            //添加爱签用户
//            rentalDataUtil.addPersonalUserV2(user.getMobile(), user.getCardName(), user.getCardNum());

            Integer successNum = loanOrderByMybatisMapper.selectNumByLoanSuccess(user.getId());
            successNum = successNum == null ? 0 : successNum;

            Integer loanPeriod = product.getLoanPeriod();
            Integer loanPeriodDay = product.getLoanDay() / loanPeriod;

            LoanOrderByMybatis loanOrder = new LoanOrderByMybatis();
            loanOrder.setUserId(loanOrderVo.getOpId());
            loanOrder.setChannelId(user.getChannelId());
            loanOrder.setMoney(product.getMoney());
            loanOrder.setStatus(OrderStatus.wait_auth.getStatus());
            loanOrder.setCreateTime(new Date());
            loanOrder.setIsDelete(false);
            loanOrder.setAppShow(true);
            loanOrder.setSignStatus(SignStatus.wait_create.getType());
            loanOrder.setReasonType(loanOrderVo.getReasonType());
            loanOrder.setOverdueFine(BigDecimal.ZERO);
            loanOrder.setShopMoney(BigDecimal.ZERO);
            loanOrder.setOrderNum(successNum + 1);
            loanOrder.setYearRate(product.getYearRate());
            loanOrder.setPayMoney(BigDecimal.ZERO);
            loanOrder.setProductId(product.getId());
            loanOrder.setDiscountsMoney(BigDecimal.ZERO);
            loanOrder.setDiscountsMoneyByGoods(BigDecimal.ZERO);
            loanOrder.setPayMoneyByGoods(BigDecimal.ZERO);
            loanOrder.setPeriod(loanPeriod);
            loanOrder.setPeriodDay(loanPeriodDay);
            loanOrder.setOverdueStatus(true);
            loanOrder.setHisOverdueStatus(true);
            loanOrder.setBankId(loanOrderVo.getBankId());
            loanOrder.setOverdueDay(0);
            loanOrder.setAuthServiceId(serviceId);
            loanOrder.setGoodsId(goodsSizeByMybatis.getGoodsId());
            loanOrder.setGoodsSizeId(goodsSizeByMybatis.getId());
            if (StringUtils.hasText(loanOrderVo.getOpIp())) {
                loanOrder.setOrderIp(loanOrderVo.getOpIp());
            } else {
                loanOrder.setOrderIp(user.getRegisterIp());
            }
            if (PlatformType.app.getType().equals(loanOrderVo.getPFrom())) {
                loanOrder.setFromClient(PlatformType.app.getType());
            } else {
                loanOrder.setFromClient(PlatformType.h5.getType());
            }
            if (StringUtils.hasLength(loanOrderVo.getApplyNo())) {
                loanOrder.setOtherApplyNo(loanOrderVo.getApplyNo());
            }
            GeoPoint geoPoint = new GeoPoint();
            geoPoint.setLon(0);
            geoPoint.setLat(0);
            if (StringUtils.hasText(loanOrderVo.getLocation()) && loanOrderVo.getLocation().contains(",")) {
                String[] locations = loanOrderVo.getLocation().split(",");
                geoPoint.setLon(Double.parseDouble(locations[0]));
                geoPoint.setLat(Double.parseDouble(locations[1]));
            }
//            loanOrder.setOrderLocation(geoPoint);

            if (successNum > 0) {
                //该订单渠道不显示
                loanOrder.setChannelStatistics(false);
            } else {
                loanOrder.setChannelStatistics(true);
            }

            //计算利息
            int betweenDay = loanOrder.getPeriod() * loanOrder.getPeriodDay();
            BigDecimal rateMoney = Util.getRateMoney(product.getMoney(), product.getYearRate(), betweenDay);
            loanOrder.setRateMoney(rateMoney);
            int index = loanOrderByMybatisMapper.insertSelective(loanOrder);
            if (index > 0) {
                if (StringUtils.hasText(loanOrderVo.getDeviceInfo()) && JSON.isValidObject(loanOrderVo.getDeviceInfo())) {
                    LoanOrderDeviceInfoByMybatis loanOrderDeviceInfoByMybatis = JSON.parseObject(loanOrderVo.getDeviceInfo(), LoanOrderDeviceInfoByMybatis.class);
                    loanOrderDeviceInfoByMybatis.setUserId(loanOrder.getUserId());
                    loanOrderDeviceInfoByMybatis.setOrderId(loanOrder.getId());
                    loanOrderDeviceInfoByMybatisMapper.insertSelective(loanOrderDeviceInfoByMybatis);
                }
                UserByMybatis updateUser = new UserByMybatis();
                updateUser.setCreateOrder(true);
                updateUser.setId(loanOrder.getUserId());
                userByMybatisMapper.updateByPrimaryKeySelective(updateUser);

                //账单
                List<LoanOrderBillByMybatis> periodDateList = Util.getPeriodList(loanOrder);
                for (int i = 0; i < periodDateList.size(); i++) {
                    LoanOrderBillByMybatis loanOrderBillByMybatis = periodDateList.get(i);
                    loanOrderBillByMybatisMapper.insertSelective(loanOrderBillByMybatis);
                }
                msgService.newMsgByAdmin(serviceId);
                if (StringUtils.hasText(loanOrderVo.getLocation())) {
                    asyncService.updateLocation(loanOrder.getId(), loanOrderVo.getLocation());
                }

                if (isar || totalNum > 0) {
                    //融担用户校验
                    userService.rdUserCheck(user);
                }
                //插入物流记录
                LoanOrderLogisticsByMybatis loanOrderLogisticsByMybatis = new LoanOrderLogisticsByMybatis();
                loanOrderLogisticsByMybatis.setOrderId(loanOrder.getId());
                loanOrderLogisticsByMybatis.setAddressInfo(loanOrderVo.getAddress());
                loanOrderLogisticsByMybatis.setAddressName(loanOrderVo.getName());
                loanOrderLogisticsByMybatis.setAddressPhone(loanOrderVo.getMobile());
                loanOrderLogisticsByMybatis.setCreateTime(new Date());
                loanOrderLogisticsByMybatisMapper.insertSelective(loanOrderLogisticsByMybatis);

                //机审
                machineRuleService.createUpdateMachineReportByASync(user.getId());
                return new ResResult(Code.SUCCESS, loanOrder.getId());
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(Util.GetErrorDetails(e));
        } finally {
            if (jedis != null) {
                redisLockUtil.release(jedis, lockKey, lockValue);
                jedis.close();
            }
        }
        return new ResResult(Code.FAIL);
    }

    @Override
    public ResResult getBill(LoanOrderVo loanOrderVo) {
        if (loanOrderVo.getProductId() == null) {
            return new ResResult(Code.PARAM_LACK);
        }
        ProductByMybatis product = productByMybatisMapper.selectByPrimaryKey(loanOrderVo.getProductId());
        if (product == null) {
            return new ResResult(Code.PARAM_INVALID);
        }
        Integer loanPeriod = product.getLoanPeriod();
        Integer loanPeriodDay = product.getLoanDay() / loanPeriod;

        Integer successNum = loanOrderByMybatisMapper.selectNumByLoanSuccess(loanOrderVo.getOpId());
        successNum = successNum == null ? 0 : successNum;

        LoanOrderByMybatis loanOrderByMybatis = new LoanOrderByMybatis();
        loanOrderByMybatis.setYearRate(product.getYearRate());
        loanOrderByMybatis.setMoney(product.getMoney());
        loanOrderByMybatis.setPeriod(loanPeriod);
        loanOrderByMybatis.setPeriodDay(loanPeriodDay);
        //计算利息
        BigDecimal rateMoney = Util.getRateMoney(product.getMoney(), product.getYearRate(), product.getLoanDay());
        loanOrderByMybatis.setRateMoney(rateMoney);

        return new ResResult(Code.SUCCESS, Util.getPeriodList(loanOrderByMybatis));
    }

    @Override
    public ResResult detail(LoanOrderVo loanOrderVo) {
        if (loanOrderVo.getOrderId() == null) {
            return new ResResult(Code.PARAM_LACK);
        }
        LoanOrderByMybatis loanOrderByMybatis = loanOrderByMybatisMapper.selectByPrimaryKey(loanOrderVo.getOrderId());
        if (loanOrderByMybatis == null || loanOrderVo.getOpId().intValue() != loanOrderByMybatis.getUserId()) {
            return new ResResult(Code.SUCCESS, null);
        }
        loanOrderByMybatis.setCreateTimeStr(DateUtil.formatDateTime(loanOrderByMybatis.getCreateTime()));
        loanOrderByMybatis.setLoanTimeStr(DateUtil.formatDateTime(loanOrderByMybatis.getLoanTime()));
        List<LoanOrderBillByMybatis> billByMybatisList = loanOrderBillByMybatisMapper.selectListByOrder(loanOrderByMybatis.getId());
        for (LoanOrderBillByMybatis loanOrderBillByMybatis : billByMybatisList) {
            loanOrderBillByMybatis.setUnPayMoney(Util.getUnPayMoney(loanOrderBillByMybatis));

            //本息已还、担保费已还
            BigDecimal piPayMoney = loanOrderPayLogByMybatisMapper.selectSumByBillId(loanOrderBillByMybatis.getId(), null, PayType.principal_interest.getType());
            piPayMoney = piPayMoney == null ? BigDecimal.ZERO : piPayMoney;

            //查询该账户本息待还金额
            BigDecimal piUnPayMoney = Util.getUnPayMoneyByPi(loanOrderBillByMybatis.getMoney(), loanOrderBillByMybatis.getRateMoney(), loanOrderBillByMybatis.getOverdueFine(), piPayMoney, loanOrderBillByMybatis.getDiscountsMoney());

            loanOrderBillByMybatis.setPiPayMoney(piPayMoney);
            loanOrderBillByMybatis.setPiUnPayMoney(piUnPayMoney);

            loanOrderBillByMybatis.setPayTimeStr(DateUtil.formatDateTime(loanOrderBillByMybatis.getPayTime()));
        }

        loanOrderByMybatis.setGoods(goodsByMybatisMapper.selectByPrimaryKey(loanOrderByMybatis.getGoodsId()));
        List<LoanOrderLogisticsByMybatis> loanOrderLogisticsByMybatisList = new ArrayList<>();
        loanOrderLogisticsByMybatisList.add(loanOrderLogisticsByMybatisMapper.selectByOrderId(loanOrderByMybatis.getId()));
        loanOrderByMybatis.setLogistics(loanOrderLogisticsByMybatisList);
        loanOrderByMybatis.setLoanOrderBills(billByMybatisList);
        loanOrderByMybatis.setLoanOrderSignLogs(loanOrderSignLogByMybatisMapper.selectLastByOrderId(loanOrderByMybatis.getId()));
        UserBankByMybatis userBankByMybatis = userBankByMybatisMapper.selectByPrimaryKey(loanOrderByMybatis.getBankId());
        if (userBankByMybatis != null) {
            loanOrderByMybatis.setBankInfo(userBankByMybatis.getBankName() + "(" + userBankByMybatis.getCarNo().substring(userBankByMybatis.getCarNo().length() - 4) + ")");
        }
        return new ResResult(Code.SUCCESS, loanOrderByMybatis);
    }

    @Override
    public ResResult list(LoanOrderVo loanOrderVo) {
        PageHelper.startPage(loanOrderVo.getPageNum(), loanOrderVo.getPageSize());
        LoanOrderByMybatis signOrderByMybatis = new LoanOrderByMybatis();
        signOrderByMybatis.setUserId(loanOrderVo.getOpId());
        signOrderByMybatis.setAppShow(true);
        Page<LoanOrderByMybatis> signOrderByMybatisPage = loanOrderByMybatisMapper.selectByList(signOrderByMybatis);
        for (LoanOrderByMybatis loanOrderByMybatis : signOrderByMybatisPage) {
            loanOrderByMybatis.setCreateTimeStr(DateUtil.formatDateTime(loanOrderByMybatis.getCreateTime()));
            loanOrderByMybatis.setGoods(goodsByMybatisMapper.selectByPrimaryKey(loanOrderByMybatis.getGoodsId()));
        }
        return new ResResult(signOrderByMybatisPage, signOrderByMybatisPage.getPages(), signOrderByMybatisPage.getTotal());
    }


    @Override
    public ResResult getLocationInfo(LoanOrderVo loanOrderVo) {
        LoanOrderByMybatis loanOrderByMybatis = loanOrderByMybatisMapper.selectByPrimaryKey(loanOrderVo.getOrderId());
        //周边下单数量
        List<Integer> distanceList = new ArrayList<>();
        distanceList.add(100);
        distanceList.add(1000);
        distanceList.add(3000);
        distanceList.add(5000);
        distanceList.add(10000);
        distanceList.add(100000);

        LoanOrderByMybatis search = new LoanOrderByMybatis();
//        search.setLongitude(loanOrderByMybatis.getOrderLocation().getLon());
//        search.setLatitude(loanOrderByMybatis.getOrderLocation().getLat());
        search.setUserId(loanOrderByMybatis.getUserId());
        List<JSONObject> disInfo = new ArrayList<>();
        for (Integer integer : distanceList) {
            search.setDistance(integer);
            Integer number = loanOrderByMybatisMapper.selectNumByPoint(search);
            number = number == null ? 0 : number;

            JSONObject itemJs = new JSONObject();
            itemJs.put("distance", integer);
            itemJs.put("number", number);
            disInfo.add(itemJs);
        }

        JSONObject dataJs = new JSONObject();
        dataJs.put("disInfo", disInfo);
        if (StringUtils.hasLength(loanOrderByMybatis.getLocationAddress())) {
            dataJs.put("locationAddress", loanOrderByMybatis.getLocationAddress());
        } else {
            dataJs.put("locationAddress", "用户未授权定位");
        }
        return new ResResult(Code.SUCCESS, dataJs);
    }


    @Override
    public ResResult getOrderListByUser(LoanOrderVo loanOrderVo) {
        if (loanOrderVo.getUserId() == null) {
            return new ResResult(Code.PARAM_LACK);
        }
        List<LoanOrderByMybatis> loanOrderByMybatisList = loanOrderByMybatisMapper.selectByUser(loanOrderVo.getUserId());
        if (loanOrderByMybatisList == null || loanOrderByMybatisList.size() == 0) {
            return new ResResult(Code.SUCCESS);
        }
        for (LoanOrderByMybatis loanOrderByMybatis : loanOrderByMybatisList) {
            //审核备注
            List<String> authByMybatisList = loanOrderAuthByMybatisMapper.selectReasonByOrder(loanOrderByMybatis.getId());
            if (authByMybatisList != null && authByMybatisList.size() > 0) {
                loanOrderByMybatis.setSqlEx(authByMybatisList.toString());
            } else {
                loanOrderByMybatis.setSqlEx("");
            }

            loanOrderByMybatis.setStartTimeByCreate(DateUtil.formatDateTime(loanOrderByMybatis.getCreateTime()));
            List<LoanOrderBillByMybatis> loanOrderBillByMybatisList = loanOrderBillByMybatisMapper.selectListByOrder(loanOrderByMybatis.getId());
            for (LoanOrderBillByMybatis loanOrderBillByMybatis : loanOrderBillByMybatisList) {
                loanOrderBillByMybatis.setPayTimeStr(DateUtil.formatDate(loanOrderBillByMybatis.getPayTime()));
                if (loanOrderBillByMybatis.getOpTime() != null) {
                    loanOrderBillByMybatis.setOpTimeStr(DateUtil.formatDateTime(loanOrderBillByMybatis.getOpTime()));
                }
            }
            loanOrderByMybatis.setLoanOrderBills(loanOrderBillByMybatisList);
        }
        return new ResResult(Code.SUCCESS, loanOrderByMybatisList);
    }


    @Override
    public ResResult updateBlack(LoanOrderVo loanOrderVo) {
        if (loanOrderVo.getUserId() == null) {
            return new ResResult(Code.PARAM_LACK);
        }
        UserByMybatis userByMybatis = userByMybatisMapper.selectByPrimaryKey(loanOrderVo.getUserId());
        if (userByMybatis == null || userByMybatis.getId() == null) {
            return new ResResult(Code.PARAM_INVALID);
        }
        userService.rdUserCheck(userByMybatis);
        return userService.detailByOrderId(loanOrderVo);
    }

    @Async
    @Override
    public void authLoan() {
        SettingByMybatis setting = settingService.getSetting();
        if (setting.getAutoLoan() == null || !setting.getAutoLoan()) {
            return;
        }
//        LoanOrderByMybatis search = new LoanOrderByMybatis();
//        search.setStatus(OrderStatus.wait_loan.getStatus());
//        search.setSignStatus(SignStatus.success.getType());
//        List<LoanOrderByMybatis> loanOrderByMybatisList = loanOrderByMybatisMapper.selectByList(search);
//        for (LoanOrderByMybatis loanOrderByMybatis : loanOrderByMybatisList) {
//            //查询是否有放款记录  有则等待手动放款
//            Integer loanNum = payOrderThirdByMybatisMapper.selectNum(loanOrderByMybatis.getId());
//            if (loanNum != null && loanNum > 0) {
//                log.info("订单:{},存在放款记录 需要手动放款", loanOrderByMybatis.getId());
//                continue;
//            }
//            ResResult loanRes = loanOrderUtil.loan(loanOrderByMybatis.getId(), null);
//            log.info("订单:{},放款结果:{}", loanOrderByMybatis.getId(), JSON.toJSONString(loanRes));
//        }
    }

    @Override
    public void overdueTask() {
        /**
         * 查询实际已经逾期 但是订单状态还未逾期的订单
         */
        List<LoanOrderBillByMybatis> orderBillList = loanOrderBillByMybatisMapper.selectListByOverdue(DateUtil.beginOfDay(new Date()).toString(), null);
        if (orderBillList != null) {
            HashMap<String, Integer> mobileMap = new HashMap<>();
            for (LoanOrderBillByMybatis loanOrderBillByMybatis : orderBillList) {
                String payDate = DateUtil.formatDate(loanOrderBillByMybatis.getPayTime());
                String nowDate = DateUtil.today();

                Long dueDay = DateUtil.between(DateUtil.parseDate(payDate), DateUtil.parseDate(nowDate), DateUnit.DAY);
                LoanOrderBillByMybatis update = new LoanOrderBillByMybatis();
                update.setOverdueStatus(false);
                update.setId(loanOrderBillByMybatis.getId());
                loanOrderBillByMybatisMapper.updateByPrimaryKeySelective(update);

                //同时修改订单为当前逾期
                LoanOrderByMybatis userOrderByMybatis = new LoanOrderByMybatis();
                userOrderByMybatis.setId(loanOrderBillByMybatis.getOrderId());
                userOrderByMybatis.setOverdueStatus(false);
                userOrderByMybatis.setHisOverdueStatus(false);
                userOrderByMybatis.setOverdueDay(dueDay.intValue());
                loanOrderByMybatisMapper.updateByPrimaryKeySelective(userOrderByMybatis);

                if (loanOrderBillByMybatis.getOverdueStatus()) {
                    //今天逾期  通知短信
                    if (StringUtils.hasText(loanOrderBillByMybatis.getMobile())) {
                        mobileMap.put(loanOrderBillByMybatis.getMobile(), 1);
                    }
                }
            }

            String mobileStr = org.apache.commons.lang3.StringUtils.join(mobileMap.keySet(), ",");
            if (StringUtils.hasText(mobileStr)) {
                /**
                 * 插入库中 等待时间发送短信
                 */
                redisUtil.set(RedisCache.overdueOrderMsg + DateUtil.today(), mobileStr);
            }
        }
    }


    @Override
    public void updateOverdueDay() {
        /**
         * 更新逾期天数
         */
        List<LoanOrderBillByMybatis> orderBillByOverdueDays = loanOrderBillByMybatisMapper.selectOverdueDay(null);
        if (orderBillByOverdueDays == null || orderBillByOverdueDays.size() == 0) {
            return;
        }
        for (LoanOrderBillByMybatis loanOrderBillByMybatis : orderBillByOverdueDays) {
            String payDate = DateUtil.formatDate(loanOrderBillByMybatis.getPayTime());
            String nowDate = DateUtil.today();
            Long dueDay = DateUtil.between(DateUtil.parseDate(payDate), DateUtil.parseDate(nowDate), DateUnit.DAY);
            LoanOrderByMybatis updateOrder = new LoanOrderByMybatis();
            updateOrder.setId(loanOrderBillByMybatis.getOrderId());
            updateOrder.setOverdueDay(dueDay.intValue());
            if (dueDay == 1) {
                updateOrder.setOverdueTime(DateUtil.beginOfDay(new Date()));
            }
            loanOrderByMybatisMapper.updateByPrimaryKeySelective(updateOrder);
        }

        SettingByMybatis setting = settingService.getSetting();
        //是否自动分配催收
        if (setting.getAutoAllotCollectionService() == null || !setting.getAutoAllotCollectionService()) {
            return;
        }
        //逾期订单 若催收客服为空 则分配催收客服
        List<LoanOrderByMybatis> loanOrderByMybatisList = loanOrderByMybatisMapper.selectOverdueUnCollection();
        if (loanOrderByMybatisList == null) {
            return;
        }
        //订单列表分配催收客服
        eruptUserDataService.allotServiceByList(loanOrderByMybatisList, ServiceType.collection_service);
    }

    @Override
    public void allotAfterService() {
        SettingByMybatis setting = settingService.getSetting();
        //是否自动分配售后客服
        if (setting.getAutoAllotAfterService() == null || !setting.getAutoAllotAfterService()) {
            return;
        }
        String startTime = DateUtil.beginOfDay(new Date()).toString();
        String endTime = DateUtil.endOfDay(DateUtil.offsetDay(new Date(), 1)).toString();
        LoanOrderByMybatis search = new LoanOrderByMybatis();
        search.setStartTime(startTime);
        search.setEndTime(endTime);
        //今日到期和明日到期订单 若售后客服为空 则分配售后客服
        PageHelper.startPage(1, 99999);
        Page<LoanOrderByMybatis> userOrderByMybatisList = loanOrderByMybatisMapper.selectOrderListByDay(search);
        if (userOrderByMybatisList == null) {
            log.info("今日和明日无到期订单");
            return;
        }
        log.info("今日和明日到期订单数量:{}", userOrderByMybatisList.size());
        //订单列表分配售后客服
        eruptUserDataService.allotServiceByList(userOrderByMybatisList, ServiceType.after_service);
    }

    @Override
    public void orderStatisticDay() {
        if (DateUtil.thisHour(true) != 0) {
            return;
        }
        Date day = DateUtil.beginOfDay(new Date());
        Integer count = statisticsDayByMybatisMapper.selectExistByDay(day);
        if (count != null && count > 0) {
            log.error("日期已存在:{}", DateUtil.formatDateTime(day));
            return;
        }
        List<Integer> typeList = new ArrayList<>();
        typeList.add(3);
        typeList.add(2);
        typeList.add(1);
        for (Integer integer : typeList) {
            StatisticsDayByMybatis statisticsDayByMybatis = new StatisticsDayByMybatis();
            statisticsDayByMybatis.setType(integer);
            statisticsDayByMybatis.setDay(day);
            statisticsDayByMybatisMapper.insertSelective(statisticsDayByMybatis);
        }
    }


    /**
     * 订单上传
     */
    @Async
    @Override
    public void orderPut() {
        PageHelper.startPage(1, 99999);
        List<LoanOrderByMybatis> orderByMybatisList = loanOrderByMybatisMapper.selectPutListByIng();
        if (orderByMybatisList == null || orderByMybatisList.size() == 0) {
            return;
        }
        for (int i = orderByMybatisList.size() - 1; i >= 0; i--) {
            LoanOrderByMybatis loanOrderByMybatis = orderByMybatisList.get(i);
            if (loanOrderByMybatis.getMobile().contains(Util.prefixDel)) {
                loanOrderByMybatis.setMobile(loanOrderByMybatis.getMobile().split(Util.prefixDel)[0]);
            }
            if (loanOrderByMybatis.getIdCardNum().contains(Util.prefixDel)) {
                loanOrderByMybatis.setIdCardNum(loanOrderByMybatis.getIdCardNum().split(Util.prefixDel)[0]);
            }
            if (redisUtil.hget(RedisCache.orderPutStatus, loanOrderByMybatis.getId() + "") != null) {
                //已经上传的订单 不再提交
                orderByMybatisList.remove(i);
            }
        }
        ResResult resResult = rentalDataUtil.orderPut(orderByMybatisList);
        if (resResult.getCode().intValue() == Code.SUCCESS.getCode()) {
            for (LoanOrderByMybatis userOrderPutByMybatis : orderByMybatisList) {
                if (userOrderPutByMybatis.getStatus() == 10) {
                    //已经完成的订单 上传一次后不再上传
                    redisUtil.hset(RedisCache.orderPutStatus, userOrderPutByMybatis.getId() + "", "1");
                }
            }
        }
    }


    @Override
    public void orderHide() {
        SettingByMybatis setting = settingService.getSetting();
        /**
         * 结清订单隐藏
         */
        if (setting.getEndHideOrder() != null && setting.getEndHideOrder()) {
            loanOrderByMybatisMapper.updateOrderByHide();
        }
    }

    /**
     * 逾期订单紧急联系人上传
     */
    @Async
    @Override
    public void orderOverduePutContact() {
        PageHelper.startPage(1, 99999);
        List<OverdueContactUploadVo> overdueContactUploadVoList = userContactByMybatisMapper.selectListByOverdue();
        if (overdueContactUploadVoList == null || overdueContactUploadVoList.size() == 0) {
            return;
        }
        for (int i = overdueContactUploadVoList.size() - 1; i >= 0; i--) {
            OverdueContactUploadVo overdueContactUploadVo = overdueContactUploadVoList.get(i);
            if (redisUtil.hget(RedisCache.overdueOrderContactPutStatus, overdueContactUploadVo.getOrderId() + "") != null) {
                //已经上传的订单 不再提交
                overdueContactUploadVoList.remove(i);
            }
        }
        if (overdueContactUploadVoList.size() == 0) {
            return;
        }
        ResResult resResult = rentalDataUtil.overdueOrderContactPut(overdueContactUploadVoList);
        if (resResult.getCode().intValue() == Code.SUCCESS.getCode()) {
            for (OverdueContactUploadVo overdueContactUploadVo : overdueContactUploadVoList) {
                //上传一次后不再上传
                redisUtil.hset(RedisCache.overdueOrderContactPutStatus, overdueContactUploadVo.getOrderId() + "", "1");
            }
        }
    }


    /**
     * 拒绝用户紧急联系人上传
     */
    @Async
    @Override
    public void rejectUserPutContact() {
        PageHelper.startPage(1, 99999);
        List<OverdueContactUploadVo> overdueContactUploadVoList = userContactByMybatisMapper.selectListByRejectUser();
        if (overdueContactUploadVoList == null || overdueContactUploadVoList.size() == 0) {
            return;
        }
        for (int i = overdueContactUploadVoList.size() - 1; i >= 0; i--) {
            OverdueContactUploadVo overdueContactUploadVo = overdueContactUploadVoList.get(i);
            if (redisUtil.hget(RedisCache.rejectUserContactPutStatus, overdueContactUploadVo.getUserId() + "") != null) {
                //已经上传的订单 不再提交
                overdueContactUploadVoList.remove(i);
            }
        }
        if (overdueContactUploadVoList.size() == 0) {
            return;
        }
        ResResult resResult = rentalDataUtil.rejectUserContactPut(overdueContactUploadVoList);
        if (resResult.getCode().intValue() == Code.SUCCESS.getCode()) {
            for (OverdueContactUploadVo overdueContactUploadVo : overdueContactUploadVoList) {
                //上传一次后不再上传
                redisUtil.hset(RedisCache.rejectUserContactPutStatus, overdueContactUploadVo.getUserId() + "", "1");
            }
        }
    }


    @Override
    public void rejectUserPut() {
        Long dbLastIdByUser = null;
        Long lastIdByUser = null;
        String dbLastIdByUserStr = redisUtil.get(RedisCache.putRejectUserId);
        if (StringUtils.hasText(dbLastIdByUserStr)) {
            dbLastIdByUser = Long.parseLong(dbLastIdByUserStr);
        }
        List<RejectUserPutVo> rentalUserByMybatisList = userByMybatisMapper.selectByReject(dbLastIdByUser);
        if (rentalUserByMybatisList == null || rentalUserByMybatisList.size() <= 0) {
            return;
        }
        for (RejectUserPutVo rejectUserPutVo : rentalUserByMybatisList) {
            if (rejectUserPutVo.getMobile().contains(Util.prefixDel)) {
                rejectUserPutVo.setMobile(rejectUserPutVo.getMobile().split(Util.prefixDel)[0]);
            }
            if (rejectUserPutVo.getIdCardNum().contains(Util.prefixDel)) {
                rejectUserPutVo.setIdCardNum(rejectUserPutVo.getIdCardNum().split(Util.prefixDel)[0]);
            }
        }
        lastIdByUser = rentalUserByMybatisList.get(0).getId();
        rentalDataUtil.rejectUserPut(rentalUserByMybatisList);
        if (lastIdByUser != null) {
            redisUtil.set(RedisCache.putRejectUserId, lastIdByUser + "");
        }
    }

    @Async
    @Override
    public void orderMsgNotify() {
        SettingByMybatis setting = settingService.getSetting();
        if (setting.getMsgNotifyHour() == null || setting.getMsgNotifyHour() != DateUtil.thisHour(true)) {
            log.info("未到短信提醒时间:{}", setting.getMsgNotifyHour());
            return;
        }

        //今日到期
        Date startTime = DateUtil.beginOfDay(new Date());
        Date endTime = DateUtil.endOfDay(new Date());
        List<LoanOrderBillByMybatis> loanOrderBillByMybatisList = loanOrderBillByMybatisMapper.selectListByTomToday(startTime.toString(), endTime.toString());
        if (loanOrderBillByMybatisList != null) {
            log.info("今日到期订单数:{}", loanOrderBillByMybatisList.size());
            HashMap<String, Integer> mobileMap = new HashMap<>();
            for (LoanOrderBillByMybatis loanOrderBillByMybatis : loanOrderBillByMybatisList) {
                if (StringUtils.hasText(loanOrderBillByMybatis.getMobile())) {
                    mobileMap.put(loanOrderBillByMybatis.getMobile(), 1);
                }
            }
            String mobileStr = org.apache.commons.lang3.StringUtils.join(mobileMap.keySet(), ",");
            if (StringUtils.hasText(mobileStr)) {
                sysMsgUtil.sendToday(mobileStr);
            }
        }

        //明天到期
        startTime = DateUtil.offsetDay(startTime, 1);
        endTime = DateUtil.offsetDay(endTime, 1);
        loanOrderBillByMybatisList = loanOrderBillByMybatisMapper.selectListByTomToday(startTime.toString(), endTime.toString());
        if (loanOrderBillByMybatisList != null) {
            log.info("明日到期订单数:{}", loanOrderBillByMybatisList.size());
            HashMap<String, Integer> mobileMap = new HashMap<>();
            for (LoanOrderBillByMybatis loanOrderBillByMybatis : loanOrderBillByMybatisList) {
                if (StringUtils.hasText(loanOrderBillByMybatis.getMobile())) {
                    mobileMap.put(loanOrderBillByMybatis.getMobile(), 1);
                }
            }
            String mobileStr = org.apache.commons.lang3.StringUtils.join(mobileMap.keySet(), ",");
            if (StringUtils.hasText(mobileStr)) {
                sysMsgUtil.sendTom(mobileStr);
            }
        }

        String overdueMobiles = redisUtil.get(RedisCache.overdueOrderMsg + DateUtil.today());
        if (StringUtils.hasText(overdueMobiles)) {
            sysMsgUtil.sendOverdue(overdueMobiles);
            redisUtil.del(RedisCache.overdueOrderMsg + DateUtil.today());
        }
    }


    public void updateOrder() {
        List<LoanOrderBillByMybatis> orderBillByMybatisList = loanOrderBillByMybatisMapper.selectByDiffDay();
        if (orderBillByMybatisList == null) {
            return;
        }

        Map<Long, Long> orderIdMap = new HashMap<>();
        for (LoanOrderBillByMybatis loanOrderBillByMybatis : orderBillByMybatisList) {
            LoanOrderBillByMybatis updateBill = new LoanOrderBillByMybatis();
            updateBill.setId(loanOrderBillByMybatis.getId());
            updateBill.setPayTime(DateUtil.offsetDay(loanOrderBillByMybatis.getLoanTime(), 15 * loanOrderBillByMybatis.getPeriod() - 1));
            loanOrderBillByMybatisMapper.updateByPrimaryKeySelective(updateBill);
            orderIdMap.put(loanOrderBillByMybatis.getOrderId(), 1L);
        }

        for (Long aLong : orderIdMap.keySet()) {
            asyncService.notifyCheck(aLong);
        }

    }

}
